#include "ReadMixture.hpp"
#include "UInt.hpp"
#include "gtest_wrapper.hpp"
#include "Assertions.hpp"

namespace ui
{


class EmptyOutput : public generator::ProfileOutput
{
public:
	EmptyOutput(){};
	virtual void put(const std::vector<dna::profile>&)
	{

	}
};

class VectorOutput : public generator::ProfileOutput
{
public:
	VectorOutput(std::vector<std::vector<dna::profile>>& result) : result_(result){};
	virtual void put(const std::vector<dna::profile>& profile)
	{
		result_.push_back(profile);
	}
private:
	std::vector<std::vector<dna::profile>>& result_;
};

// 3 MARKERS
TEST(UInt, shouldFindMissingProfilesWith3MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	std::string profile_file="../input_data/3_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt, shouldFindMissingProfilesWith3MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/3_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt, shouldFindMissingProfilesWith3MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/3_markers_profile_long.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt, shouldGenerateAllPossibleProfilesWith3MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	std::vector<std::vector<dna::profile>> result;
	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new VectorOutput(result)));

	ASSERT_EQ(12*12*12, result.size());
	ASSERT_EQ(2, result[0].size()); //should return tuples
}

TEST(UInt, shouldGenerateAllPossibleProfilesWith3MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt, shouldGenerateAllPossibleProfilesWith3MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

//  5 MARKERS
TEST(UInt, shouldFindMissingProfilesWith5MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	std::string profile_file="../input_data/5_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}


TEST(UInt, shouldFindMissingProfilesWith5MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/5_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}


TEST(UInt, shouldFindMissingProfilesWith5MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/5_markers_profile_long.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt, shouldGenerateAllPossibleProfilesWith5MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));

}

TEST(UInt,  DISABLED_shouldGenerateAllPossibleProfilesWith5MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

TEST( UInt, DISABLED_shouldGenerateAllPossibleProfilesWith5MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}


TEST(UInt, shouldGenerateAllPossibleProfilesWith5Markers4Threads)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/5_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	userInterface.UnifyAndMix(mixture, 4, generator::outputPtr(new EmptyOutput()));
}


//  10 MARKERS
TEST(UInt, shouldFindMissingProfilesWith10MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	std::string profile_file="../input_data/10_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt,  DISABLED_shouldFindMissingProfilesWith10MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/10_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt,  DISABLED_shouldFindMissingProfilesWith10MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=3;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,3);

	std::string profile_file="../input_data/10_markers_profile_long.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt,  DISABLED_shouldGenerateAllPossibleProfilesWith10MarkersTwoPeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt,  DISABLED_shouldGenerateAllPossibleProfilesWith10MarkersThreePeople)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

TEST(UInt,  DISABLED_shouldGenerateAllPossibleProfilesWith10MarkersThreePeopleBetterMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=2;
	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/10_markers_mixture_long.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	userInterface.UnifyAndMix(mixture, 1, generator::outputPtr(new EmptyOutput()));
}

//  OTHER
TEST(UInt, shouldReturnOnlyOneProfileWhenGivenSpecificProfileToRemoveFromTwoPeopleMixture)
{
	UInt userInterface;
	userInterface.howManyPeople=2;

	readmixture::ReadMixture rm;
	std::string mixture_file="../input_data/3_markers_mixture.txt";
	std::vector<dna::marker> mixture=rm.parseMixFromFile(mixture_file,2);

	std::string profile_file="../input_data/3_markers_profile.txt";
	dna::profile profile=rm.parseProFromFile(profile_file);

	std::vector<std::vector<dna::profile>> result;
	userInterface.UnifyMixRemove(mixture, profile, 1, generator::outputPtr(new VectorOutput(result)));

	ASSERT_EQ(1, result.size());
	ASSERT_EQ(1, result[0].size());
	assertProfile(result[0][0], "(B,C)(F,G)(J,K)");
}
}
